/**
 * 时间轴配置管理Hook
 * 提供多粒度时间视图的配置和状态管理
 */

import { useState, useCallback, useMemo } from 'react';
import type { ViewConfig } from '../../../types/room';
import { TIME_VIEW_CONFIGS } from '../components/TimeAxisSelector';

export interface TimeAxisState {
  currentView: string;
  startDate: Date;
  endDate: Date;
  dateRange: number;
  config: ViewConfig;
}

export interface UseTimeAxisConfigReturn {
  // 当前状态
  timeAxisState: TimeAxisState;

  // 生成的数据
  dates: string[];
  dateInfos: Array<{
    date: string;
    dayOfWeek: string;
    isToday: boolean;
    isWeekend: boolean;
    hour?: number;
    week?: number;
    month?: number;
  }>;

  // 操作方法
  changeView: (viewType: string, config: ViewConfig) => void;
  changeRange: (startDate: Date, endDate: Date, days: number) => void;
  setQuickRange: (days: number) => void;
  navigateTime: (direction: 'prev' | 'next') => void;
  goToToday: () => void;

  // 工具方法
  formatDateForView: (date: Date) => string;
  isDateInRange: (date: Date) => boolean;
  getDateIndex: (date: Date) => number;
}

/**
 * 时间轴配置管理Hook
 */
export const useTimeAxisConfig = (
  initialView: string = 'day'
): UseTimeAxisConfigReturn => {
  const [currentView, setCurrentView] = useState<string>(initialView);
  const [startDate, setStartDate] = useState<Date>(new Date());
  const [dateRange, setDateRange] = useState<number>(
    TIME_VIEW_CONFIGS[initialView].dateRange
  );

  // 计算结束日期
  const endDate = useMemo(() => {
    const config = TIME_VIEW_CONFIGS[currentView];
    const end = new Date(startDate);

    if (config.type === 'hour') {
      end.setHours(end.getHours() + dateRange);
    } else {
      end.setDate(end.getDate() + dateRange);
    }

    return end;
  }, [startDate, dateRange, currentView]);

  // 当前配置
  const config = useMemo(() => TIME_VIEW_CONFIGS[currentView], [currentView]);

  // 时间轴状态
  const timeAxisState: TimeAxisState = useMemo(
    () => ({
      currentView,
      startDate,
      endDate,
      dateRange,
      config,
    }),
    [currentView, startDate, endDate, dateRange, config]
  );

  // 生成日期数组和详细信息
  const { dates, dateInfos } = useMemo(() => {
    const dates: string[] = [];
    const dateInfos: Array<{
      date: string;
      dayOfWeek: string;
      isToday: boolean;
      isWeekend: boolean;
      hour?: number;
      week?: number;
      month?: number;
    }> = [];

    const today = new Date();
    const current = new Date(startDate);

    for (let i = 0; i < dateRange; i++) {
      let dateStr: string;
      let dayOfWeek: string;
      let isToday: boolean;
      let isWeekend: boolean;

      switch (config.type) {
        case 'hour':
          dateStr = `${(current.getMonth() + 1).toString().padStart(2, '0')}/${current.getDate().toString().padStart(2, '0')} ${current.getHours().toString().padStart(2, '0')}:00`;
          dayOfWeek =
            current.getHours() === 0
              ? ['日', '一', '二', '三', '四', '五', '六'][current.getDay()]
              : '';
          isToday = current.toDateString() === today.toDateString();
          isWeekend = current.getDay() === 0 || current.getDay() === 6;

          dateInfos.push({
            date: dateStr,
            dayOfWeek,
            isToday,
            isWeekend,
            hour: current.getHours(),
          });

          current.setHours(current.getHours() + 1);
          break;

        case 'day':
          dateStr = `${(current.getMonth() + 1).toString().padStart(2, '0')}/${current.getDate().toString().padStart(2, '0')}`;
          dayOfWeek = ['日', '一', '二', '三', '四', '五', '六'][
            current.getDay()
          ];
          isToday = current.toDateString() === today.toDateString();
          isWeekend = current.getDay() === 0 || current.getDay() === 6;

          dateInfos.push({
            date: dateStr,
            dayOfWeek,
            isToday,
            isWeekend,
          });

          current.setDate(current.getDate() + 1);
          break;

        case 'week': {
          const weekStart = new Date(current);
          weekStart.setDate(weekStart.getDate() - weekStart.getDay());

          dateStr = `第${getWeekNumber(weekStart)}周`;
          dayOfWeek = `${(weekStart.getMonth() + 1).toString().padStart(2, '0')}/${weekStart.getDate().toString().padStart(2, '0')}`;
          isToday = isDateInWeek(today, weekStart);
          isWeekend = false; // 周视图不区分周末

          dateInfos.push({
            date: dateStr,
            dayOfWeek,
            isToday,
            isWeekend,
            week: getWeekNumber(weekStart),
          });

          current.setDate(current.getDate() + 7);
          break;
        }

        case 'month': {
          dateStr = `${current.getFullYear()}-${(current.getMonth() + 1).toString().padStart(2, '0')}`;
          dayOfWeek = `${current.getFullYear()}年${current.getMonth() + 1}月`;
          isToday =
            current.getFullYear() === today.getFullYear() &&
            current.getMonth() === today.getMonth();
          isWeekend = false; // 月视图不区分周末

          dateInfos.push({
            date: dateStr,
            dayOfWeek,
            isToday,
            isWeekend,
            month: current.getMonth() + 1,
          });

          current.setMonth(current.getMonth() + 1);
          break;
        }

        default:
          dateStr = current.toISOString().split('T')[0];
          dayOfWeek = ['日', '一', '二', '三', '四', '五', '六'][
            current.getDay()
          ];
          isToday = current.toDateString() === today.toDateString();
          isWeekend = current.getDay() === 0 || current.getDay() === 6;

          dateInfos.push({
            date: dateStr,
            dayOfWeek,
            isToday,
            isWeekend,
          });

          current.setDate(current.getDate() + 1);
          break;
      }

      dates.push(dateStr);
    }

    return { dates, dateInfos };
  }, [startDate, dateRange, config.type]);

  // 切换视图
  const changeView = useCallback((viewType: string, newConfig: ViewConfig) => {
    setCurrentView(viewType);
    setDateRange(newConfig.dateRange);

    // 调整开始日期以适应新视图
    const now = new Date();
    if (newConfig.type === 'hour') {
      // 小时视图从当前小时开始
      now.setMinutes(0, 0, 0);
    } else if (newConfig.type === 'week') {
      // 周视图从本周周一开始
      const dayOfWeek = now.getDay();
      const diff = dayOfWeek === 0 ? -6 : 1 - dayOfWeek;
      now.setDate(now.getDate() + diff);
    } else if (newConfig.type === 'month') {
      // 月视图从本月1号开始
      now.setDate(1);
    }

    setStartDate(now);
  }, []);

  // 改变时间范围
  const changeRange = useCallback(
    (newStartDate: Date, newEndDate: Date, days: number) => {
      setStartDate(new Date(newStartDate));
      setDateRange(days);
    },
    []
  );

  // 快速范围设置
  const setQuickRange = useCallback((days: number) => {
    const now = new Date();
    setStartDate(now);
    setDateRange(days);
  }, []);

  // 时间导航
  const navigateTime = useCallback(
    (direction: 'prev' | 'next') => {
      const multiplier = direction === 'next' ? 1 : -1;
      const newStartDate = new Date(startDate);

      let offset: number;
      switch (config.type) {
        case 'hour':
          offset = 24 * multiplier; // 前进/后退24小时
          newStartDate.setHours(newStartDate.getHours() + offset);
          break;
        case 'day':
          offset = 7 * multiplier; // 前进/后退7天
          newStartDate.setDate(newStartDate.getDate() + offset);
          break;
        case 'week':
          offset = 28 * multiplier; // 前进/后退4周
          newStartDate.setDate(newStartDate.getDate() + offset);
          break;
        case 'month':
          offset = 3 * multiplier; // 前进/后退3个月
          newStartDate.setMonth(newStartDate.getMonth() + offset);
          break;
        default:
          offset = dateRange * multiplier;
          newStartDate.setDate(newStartDate.getDate() + offset);
      }

      setStartDate(newStartDate);
    },
    [startDate, config.type, dateRange]
  );

  // 回到今天
  const goToToday = useCallback(() => {
    const now = new Date();

    if (config.type === 'hour') {
      now.setMinutes(0, 0, 0);
    } else if (config.type === 'week') {
      const dayOfWeek = now.getDay();
      const diff = dayOfWeek === 0 ? -6 : 1 - dayOfWeek;
      now.setDate(now.getDate() + diff);
    } else if (config.type === 'month') {
      now.setDate(1);
    }

    setStartDate(now);
  }, [config.type]);

  // 格式化日期
  const formatDateForView = useCallback(
    (date: Date): string => {
      switch (config.type) {
        case 'hour':
          return `${(date.getMonth() + 1).toString().padStart(2, '0')}/${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:00`;
        case 'day':
          return `${(date.getMonth() + 1).toString().padStart(2, '0')}/${date.getDate().toString().padStart(2, '0')}`;
        case 'week':
          const weekStart = new Date(date);
          weekStart.setDate(weekStart.getDate() - weekStart.getDay());
          return `第${getWeekNumber(weekStart)}周`;
        case 'month':
          return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}`;
        default:
          return date.toISOString().split('T')[0];
      }
    },
    [config.type]
  );

  // 检查日期是否在范围内
  const isDateInRange = useCallback(
    (date: Date): boolean => {
      return date >= startDate && date <= endDate;
    },
    [startDate, endDate]
  );

  // 获取日期索引
  const getDateIndex = useCallback(
    (date: Date): number => {
      const formattedDate = formatDateForView(date);
      return dates.indexOf(formattedDate);
    },
    [dates, formatDateForView]
  );

  return {
    timeAxisState,
    dates,
    dateInfos,
    changeView,
    changeRange,
    setQuickRange,
    navigateTime,
    goToToday,
    formatDateForView,
    isDateInRange,
    getDateIndex,
  };
};

// 工具函数
function getWeekNumber(date: Date): number {
  const firstDayOfYear = new Date(date.getFullYear(), 0, 1);
  const pastDaysOfYear = (date.getTime() - firstDayOfYear.getTime()) / 86400000;
  return Math.ceil((pastDaysOfYear + firstDayOfYear.getDay() + 1) / 7);
}

function isDateInWeek(date: Date, weekStart: Date): boolean {
  const weekEnd = new Date(weekStart);
  weekEnd.setDate(weekStart.getDate() + 6);
  return date >= weekStart && date <= weekEnd;
}

export default useTimeAxisConfig;
